#include <iostream>
#include <vector>
#include <fstream>
#include <stdlib.h>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <map>

#define MAXTABN 100
#define MAXTABM 100

using namespace std;

int main(int argc, char *argv[]) {	
// ./generador n m cFichasDelTab cFichasRandom conSolucion

// donde conSolucion genera un caso en el que tiene muchas fichas de 1x1 blancas y negras para completar todo el tablero, ademas de las otras fichas
//si no se escribe nada en ese parametro genera uno con menos fichitas, es mas dificil entonces que tenga sol, aunque podria llegar a tener dependiendo de las otras fichas.		
		std::ofstream output;
		if (argc<6){
			printf("ERROR faltan parametros: n m cFichasDelTab cFichasRandom conSolucion\n");
			printf("n m, mayores a 1. Si se pone algo distinto a 'conSolucion', genera algo random que puede o no tener solucion\n");
			
			return 1;		
		}		
		int n = atoi(argv[1]);
		int m = atoi(argv[2]);
		if (n>MAXTABN || m>MAXTABM){
			printf("ERROR el tamaño maximo de un tablero es de 100x100\n");
			return 1;		
		}
		if (n==0 || m==0){
			printf("ERROR n y m tienen que ser mayores a 0\n");
			return 1;		
		}
		int cFichasDelTab = atoi(argv[3]);
		int cFichasRandom = atoi(argv[4]);
		bool tieneSol = std::string (argv[5]) == "conSolucion";
	
		int cantBlancas = 0;
		int cantNegras = 0;
				
		vector<vector<bool> > tablero(n);
		
		for (int i = 0; i<n; i++){
			tablero[i].resize(m);
			for (int j = 0; j<m; j++){	
				tablero[i][j] =  (rand() % 2);
				if (tablero[i][j]){
					cantBlancas++;
				}else{
					cantNegras++;
				}
			}
		}
		
		int cFichitasB;
		int cFichitasN;
		if (tieneSol){
			cFichitasB = cantBlancas;
			cFichitasN = cantNegras;
		}else{
			cFichitasB = (rand() % (n*m/2));
			cFichitasN = (rand() % (n*m/2));
		}
		
		output.open("p4.in");
		int totalFichas = cFichasDelTab + cFichasRandom + cFichitasN + cFichitasB;
		output << n << " " << m << " " << totalFichas << "\n";
		//Imprimo el tablero		
		for (int i = 0; i<n; i++){
			for (int j = 0; j<m; j++){	
				if (tablero[i][j]){
					output << 1;
				}else{
					output << 0;
				}
				if (j+1<m) output << " "; //Si hay siguiente pongo un espacio
			}
			output << "\n"; //Nueva linea
		}
		//Fin imprimir tablero

		//Imprimo fichas Random

		for (int c = 0; c<cFichasRandom; c++){
			int cFilas = (rand() % n) +1;
			int cCol = (rand() % m) +1;
			output << cFilas << " " << cCol << "\n";
			for (int i = 0; i<cFilas; i++){
				for (int j = 0; j<cCol; j++){	
					output << (rand() % 2);
					if (j+1<m) output << " "; //Si hay siguiente pongo un espacio
				}
				output << "\n"; //Nueva linea
			}
		}
		

		//Imprimo Fichas del tablero

		for (int c = 0; c<cFichasDelTab; c++){
			// Busco desde donde hasta donde del tablero pertenece la ficha
			int iniFila = (rand() % (n-1)) +1;
			int cFilas = (rand() % (n-iniFila)) +1;			
			int iniCol = (rand() % (m-1)) +1;
			int cCol = (rand() % (m-iniCol)) +1;
			output << cFilas << " " << cCol << "\n";
			for (int i = 0; i<cFilas; i++){
				for (int j = 0; j<cCol; j++){	
					if (tablero[iniFila+i][iniCol+j]){
						output << 1;
					}else{
						output << 0;
					}
					if (j+1<m) output << " "; //Si hay siguiente pongo un espacio
				}
				output << "\n"; //Nueva linea
			}
		}
		
		//Imprimo Fichitas blancas y negras de 1x1

		for (int c = 0; c<cFichitasB; c++){
			output << 1 << " " << 1 << "\n";
			output << 1 << "\n";	//Imprimo 1 para Blanco
		}
		for (int c = 0; c<cFichitasN; c++){
			output << 1 << " " << 1 << "\n";
			output << 0 << "\n"; //Imprimo 0 para Negro
		}
		output << "#";	
		output.close();
	return 0;
}


